package com.samsung.sds.test.editors;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.ui.model.IWorkbenchAdapter;

abstract public class JSElement implements IWorkbenchAdapter, IAdaptable, JSElementCategories {
	protected String name;
	protected int offset;
	protected int numberOfLines;
	protected int length;

	protected JSElement parent;
	protected List children;

	protected JSElement reference;
	protected JSScope scope = new JSScope();

	public JSElement(String aName, int offset, int length) {
		this.name = aName;
		this.offset = offset;
		this.length = length;
		this.children = new LinkedList();
		
		scope.setScopeName(aName);
	}

	public Object getAdapter(Class adapter) {
		if (adapter == IWorkbenchAdapter.class) {
			return this;
		}

		return null;
	}

	public String getLabel(Object o) {
		return name;
	}

	public int getLength() {
		return length;
	}

	public int getNumberOfLines() {
		return numberOfLines;
	}

	public int getStart() {
		return offset;
	}

	public void setNumberOfLines(int newNumberOfLines) {
		numberOfLines = newNumberOfLines;
	}

	public String toString() {
		return getLabel(this);
	}

	public Object[] getChildren(Object o) {
		Object[] result = new Object[children.size()];
		return children.toArray(result);
	}

	public Object getParent(Object o) {
		return null;
	}

	abstract public int category();

	public String getName() {
		return name;
	}

	public int getOffset() {
		return offset;
	}

	public JSElement getParent() {
		return parent;
	}

	protected void setParent(JSElement element) {
		parent = element;
		System.out.println(this.getName() + " class is a child of " + parent.getName() + " class.");
	}

	public boolean sharesParentWith(JSElement anElement) {
		if (parent == null) {
			return anElement.getParent() == null;
		}

		return parent.equals(anElement.getParent());
	}

	public boolean equals(JSElement anElement) {
		return sharesParentWith(anElement) && name.equals(anElement.getName());
	}

	public static JSElement castInstanceToVariable(JSInstanceVariableElement instance) {
		return new JSVariableElement(instance.getName(), instance.getOffset(), instance.getLength());
	}

	public static JSElement castVariableToInstance(JSVariableElement variable) {
		return new JSInstanceVariableElement(variable.getName(), variable.getOffset(), variable.getLength());
	}

	public JSElement getReference() {
		return reference;
	}

	public void setReference(JSElement reference) {
		this.reference = reference;
	}

	public JSScope getScope() {
		return scope;
	}

	public void setScope(JSScope scope) {
		this.scope = scope;
	}

}